class Hiker {

    framesize;
    framesizeHD;
    type;
    target_index;
    target_points;
    win_path;
    vel;
    collision_radius;
    hikerpointer;
    frames;

    isLoaded: boolean;
    isDead: boolean;
    currentTarget;
    pos;
    last;
    sintick;
    sinvalue;
    image;
    flipped;
    state;

    constructor(hikerdata) {
        this.init(hikerdata);
    }
    init(hikerdata) {
        window.game.Entity.init.apply(this, null); //sets up a basic entity

        this.framesize = { x: 129, y: 187 };
        this.framesizeHD = { x: 242, y: 351 };

        this.type = 'hiker';

        this.target_index = 0;
        this.target_points = [ //normal path a hiker follows up the mountain
            { x: 500, y: 1350 },
            { x: 559, y: 1050 },
            { x: 55, y: 850 },
            { x: 55, y: 830 },
            { x: 550, y: 585 },
            { x: 552, y: 565 },
            { x: 170, y: 410 },
            { x: 450, y: 280 },
            { x: 450, y: 245 },
            { x: 260, y: 160 },
            { x: 360, y: 120 },
            { x: 360, y: -50 }
        ];
        this.win_path = [ //movement for hiker when he reaches the summit
            { x: 360, y: -50 },
            { x: 330, y: -60 },
            { x: 370, y: -70 }
        ];

        this.vel = { x: 10, y: 5, angle: 0 };
        this.collision_radius = 45;

        this.sinvalue = 0; //gives the hikers a little bounciness on movement
        this.sintick = 0;

        this.state = 'loading';
        this.hikerpointer = null;

        var hikersprite = Math.round(Math.random() * 4); //pull a random sprite for this demo
        this.frames[0] = new window.game.Frame(this.framesize.x * hikersprite, 0, this.framesize.x, this.framesize.y);
        this.image = window.game.Entity.loadimg('media/hikers_lores.png');

        //grab first target from set of points
        this.currentTarget = this.target_points[0];
        this.pos.x = this.currentTarget.x;
        this.pos.y = this.currentTarget.y;
        this.last.x = this.currentTarget.x;
        this.last.y = this.currentTarget.y;

        this.sintick = Math.max(0.6, Math.random() + 0.4); //Randomly choses bounciness of a hiker

    }


    update() {
        window.game.Entity.update_pre.apply(this, null);

        switch (this.state) {
            case 'loading':
                this.STATE_loading();
                break;
            case 'normal':
                this.STATE_normal();
                break;
            case 'struck':
                this.STATE_struck();
                break;
            case 'win':
                this.STATE_win();
                break;
            case 'gameover':
                this.STATE_gameover();
                break;
            default:
                break;
        }
        window.game.Entity.update_post.apply(this, null);
    }

    draw() {
        if (this.isLoaded === true && this.image.complete === true) {
            window.game.Entity.draw.apply(this, null); //draw using entity base
        }
    }

    kill() {
        this.isDead = true;
    }

    STATE_normal() {
        var targetvector = { x: this.currentTarget.x - this.pos.x, y: this.currentTarget.y - this.pos.y };
        if (window.game.Entity.vectorlength(targetvector) < 20) {
            this.target_index++;
            if (this.target_index < this.target_points.length) {
                this.currentTarget = this.target_points[this.target_index];
            }
            else {
                window.game.system.hikersuccess();
                this.state = 'win';
                return;
            }
        };

        var normalizedvector = window.game.Entity.normalizevector(Math.round(targetvector.x), Math.round(targetvector.y));
        this.pos.x += this.vel.x * normalizedvector.x; //move to target
        this.pos.y += this.vel.y * normalizedvector.y + (Math.sin(this.sinvalue) * 2);

        //test collision(Using Circular Collison Detection)
        var snowball_pos = window.game.system.snowball.pos;
        var snowball_col = window.game.system.snowball.collision_radius;

        var vectorTo = { x: this.pos.x - snowball_pos.x, y: this.pos.y - snowball_pos.y };

        if ((window.game.Entity.vectorlength(vectorTo) - this.collision_radius - snowball_col) < 0) {
            //collision has happened
            this.updatestats();
            this.vel.x = vectorTo.x * 0.3;
            this.vel.y = vectorTo.y * 0.3;

            this.state = 'struck';

            //notify snowball
            window.game.system.snowball.collision(vectorTo);
        }

        //flip image depending on direction traveling
        if (normalizedvector.x < 0) {
            this.flipped = false;
        }
        else if (normalizedvector.x > 0) {
            this.flipped = true;
        }

        this.sinvalue += this.sintick;

    }

    STATE_struck() {
        this.vel.x += window.game.system.map.gravity.x * 0.5;
        this.vel.y += window.game.system.map.gravity.y * 0.5;

        this.pos.x += this.vel.x;
        this.pos.y += this.vel.y;

        if (this.vel.x < 0) {
            this.pos.angle += 10;
        }
        else {
            this.pos.angle -= 10;
        }

        if (this.pos.y > 2500 || this.pos.y < -400
            || this.pos.x < -800 || this.pos.x > 1050) {
            //hiker offscreen
            this.kill();
        }
    }

    STATE_win() {
        var targetvector = { x: this.currentTarget.x - this.pos.x, y: this.currentTarget.y - this.pos.y };
        if (window.game.Entity.vectorlength(targetvector) < 10) {
            this.target_index++;
            if (this.target_index >= this.win_path.length) {
                this.target_index = 0;
            }
            this.currentTarget = this.win_path[this.target_index];
        };

        var normalizedvector = window.game.Entity.normalizevector(Math.round(targetvector.x), Math.round(targetvector.y));
        this.pos.x += this.vel.x * normalizedvector.x; //move to target
        this.pos.y += this.vel.y * normalizedvector.y + (Math.sin(this.sinvalue) * 2);
    }

    STATE_loading() {
        if (this.image.complete === true) {
            //if images arent loaded wait
            this.isLoaded = true;
            this.state = 'normal';
            return;
        }
    }

    STATE_gameover() {


    }

    updatestats() {
        //updates all the stats for the game when a hiker is killed
        window.game.system.hikerkills++; //system count for UI and gameover
    }
} 